﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

// Qt headers
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QStackedLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QFrame>
#include <QSignalMapper>
#include <QFontMetrics>
#include <QTimer>
#include <QFileInfo>

// custom headers
#include "ImageSlider.h"
#include "GbmpNew.h"
#include "DebugMessage.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 

namespace gmepgcs
{
    ImageSlider::ImageSlider(QWidget * parent) : QWidget(parent), 
        m_imageKeys(),
        m_mpImageTitles(),
        m_currentIndex(0),
        m_previousIndex(-1),
        m_mpImages(),
        m_stretch(true),
        m_bLoop(true),
        m_bAutoPlay(false),
        m_spImageProvider(nullptr),
        m_pImageFrame(nullptr),
        m_pLblImage(nullptr),
        m_pLblTitle(nullptr),
        m_pDotsSigalMapper(nullptr),
        m_mpBtnDots(),
        m_pAutoPlayTimer(nullptr)
    {
        Init();
    }

    ImageSlider::~ImageSlider()
    {
    }

    void ImageSlider::ResetImages()
    {
        m_mpImages.clear();
        SlideTo(0);
    }

    void ImageSlider::SetImages(std::vector<std::wstring> imageKeys, std::map<std::wstring, std::wstring> titles /*= {}*/)
    {
        if (m_bAutoPlay && m_pAutoPlayTimer)
        {
            m_pAutoPlayTimer->stop();
        }
        
        m_mpImages.clear();
        m_imageKeys = imageKeys;
        m_mpImageTitles = titles;

        CheckDots();
        SlideTo(0);
        
        if (m_bAutoPlay && m_pAutoPlayTimer)
        {
            m_pAutoPlayTimer->start();
        }
    }

    void ImageSlider::SlideBack()
    {
        if (m_currentIndex <= 0)
        {
            if (m_bLoop)
            {
                SlideTo((int)m_imageKeys.size() - 1);
                return;
            }
            else
            {
                return;
            }
        }

        SlideTo(m_currentIndex - 1);
    }

    void ImageSlider::SlideForward()
    {
        if (m_currentIndex >= m_imageKeys.size() - 1)
        {
            if (m_bLoop)
            {
                SlideTo(0);
                return;
            }
            else
            {
                return;
            }
        }

        SlideTo(m_currentIndex + 1);
    }

    // GMEP 本地imageKey  为全路径
    void ImageSlider::SlideTo(int32_t index)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pImageFrame, L"m_pImageFrame为空", L"GMEP", L"2024-01-30");
        m_pImageFrame->setToolTip(QString());
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblTitle, L"m_pLblTitle为空", L"GMEP", L"2024-01-30");
        m_pLblTitle->clear();
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblImage, L"m_pLblImage为空", L"GMEP", L"2024-01-30");
        m_pLblImage->clear();

        int32_t imageKeysCount = (int32_t)m_imageKeys.size();
        if (imageKeysCount <= 0)
        {
            m_currentIndex = -1;
            m_previousIndex = -1;
            return;
        }

        if (index < 0)
        {
            index = 0;
        }

        if (index > imageKeysCount - 1)
        {
            index = imageKeysCount - 1;
        }

        std::wstring imageKey = m_imageKeys[index];
        if (imageKey.size() > 0)
        {
            
            if (m_spImageProvider) // public page
            {

                if (!m_mpImages.contains(imageKey))
                {
                    m_mpImages[imageKey] = nullptr;
                }

                if (m_mpImages[imageKey])
                {
                    UpdateImage(imageKey, m_mpImages[imageKey]);
                }
                else
                {
                    m_spImageProvider->Provide(imageKey);
                }
            }
            else // project Page
            {
                if (!m_mpImages.contains(imageKey))
                {
                    QString path = QString::fromStdWString(imageKey);
                    QFileInfo fileInfo(path);
                    if (fileInfo.exists())
                    {
                        std::shared_ptr<QImage> spImage = std::make_shared<QImage>();
                        spImage->load(path);
                        m_mpImages[imageKey] = spImage;
                    }

                }
                if (m_mpImages.contains(imageKey))
                    UpdateImage(imageKey, m_mpImages[imageKey]);
            }
        }
        m_previousIndex = m_currentIndex;
        m_currentIndex = index;

        for(int i=0; i!=imageKeysCount; ++i)
        {
            if (i == index)
            {
                DBG_WARN_AND_CONTINUE_UNLESS(m_mpBtnDots[i], L"m_mpBtnDots[i]为空", L"GMEP", L"2024-01-30");   
                m_mpBtnDots[i]->setIcon(QIcon(QString::fromStdWString(L":/images/circle_#596370_16x16.png")));
            }
            else
            {
                DBG_WARN_AND_RETURN_VOID_UNLESS(m_mpBtnDots[i], L"m_mpBtnDots[i]为空", L"GMEP", L"2024-01-30");
                m_mpBtnDots[i]->setIcon(QIcon(QString::fromStdWString(L":/images/circle_#bdc7d5_16x16.png")));
            }
        }
    }

    void ImageSlider::SetImageFrameSize(const QSize & frameSize)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pImageFrame, L"m_pImageFrame为空", L"GMEP", L"2024-01-30");
        m_pImageFrame->setFixedSize(frameSize);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblImage, L"m_pLblImage为空", L"GMEP", L"2024-01-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblTitle, L"m_pLblTitle为空", L"GMEP", L"2024-01-30");
        m_pLblImage->setMaximumSize(QSize(m_pImageFrame->size().width(), m_pImageFrame->size().height() - m_pLblTitle->size().height()));

        SlideTo(m_currentIndex);
    }
    
    void ImageSlider::SetShowTitle(const bool & visible)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblTitle, L"m_pLblTitle为空", L"GMEP", L"2024-01-30");
        m_pLblTitle->setVisible(visible);
    }

    void ImageSlider::SetShowBorder(const bool & showBorder)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pImageFrame, L"m_pImageFrame为空", L"GMEP", L"2024-01-30");
        m_pImageFrame->setStyleSheet(
            "QFrame#" + m_pImageFrame->objectName() + "{"
            "border:" + (showBorder ? "1px solid rgba(217, 221, 228, 255)" : "none") + ";"
            "}"
        );
    }

    void ImageSlider::SetStretch(const bool & stretch)
    {
        if (m_stretch != stretch)
        {
            m_stretch = stretch;
            SlideTo(m_currentIndex);
        }
    }

    void ImageSlider::Init()
    {
        // main layout
        QVBoxLayout *pMainLayout = NEW_AS_QT_CHILD(QVBoxLayout, this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pMainLayout, L"pMainLayout为空", L"GMEP", L"2024-01-30");
        setLayout(pMainLayout);

        // central layout
        QHBoxLayout *pCentralLayout = NEW_AS_QT(QHBoxLayout);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCentralLayout, L"pCentralLayout为空", L"GMEP", L"2024-01-30");
        pMainLayout->addLayout(pCentralLayout);
        pCentralLayout->setContentsMargins(0, 0, 0, 0);
        pCentralLayout->setSpacing(0);

        // slide backward
        QPushButton *pBtnSlideBack = NEW_AS_QT_CHILD( QPushButton,QIcon(":/images/arrow_left.png"), QString(), this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pBtnSlideBack, L"pBtnSlideBack为空", L"GMEP", L"2024-01-30");
        pBtnSlideBack->setObjectName("SlideBack");
        pCentralLayout->addWidget(pBtnSlideBack);
        pBtnSlideBack->setCursor(QCursor(Qt::CursorShape::PointingHandCursor));
        pBtnSlideBack->setStyleSheet("QPushButton{"
            "background-color:rgba(0,0,0,0);"
            "border:none;"
            "}"
        );
        connect(pBtnSlideBack, &QPushButton::clicked, this, &ImageSlider::SlideBack);
        
        // image frame
        m_pImageFrame = NEW_AS_QT(QFrame);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pImageFrame, L"m_pImageFrame为空", L"GMEP", L"2024-01-30");
        pCentralLayout->addWidget(m_pImageFrame);
        m_pImageFrame->setObjectName("ImageFrame");
        m_pImageFrame->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
        SetShowBorder(false);

        // frame layout
        QVBoxLayout *pFrameLayout = NEW_AS_QT_CHILD(QVBoxLayout, m_pImageFrame);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pFrameLayout, L"pFrameLayout为空", L"GMEP", L"2024-01-30");
        m_pImageFrame->setLayout(pFrameLayout);
        pFrameLayout->setContentsMargins(0, 0, 0, 0);
        pFrameLayout->setSpacing(0);

        // title
        m_pLblTitle = NEW_AS_QT(QLabel);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblTitle, L"m_pLblTitle为空", L"GMEP", L"2024-01-30");
        pFrameLayout->addWidget(m_pLblTitle);
        m_pLblTitle->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
        m_pLblTitle->setFixedHeight(24);
        m_pLblTitle->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Fixed);
        m_pLblTitle->setStyleSheet(
            "QLabel{"
            "font-family:\"Microsoft YaHei\";"
            "font-size:12px;"
            "color:rgba(0,0,0,255);"
            "background:rgba(240, 240, 245, 255);"
            "padding-left:5px;"
            "padding-right:5px;"
            "}"
        );
        SetShowTitle(false);

        // image
        m_pLblImage = NEW_AS_QT(QLabel);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblImage, L"m_pLblImage为空", L"GMEP", L"2024-01-30");
        pFrameLayout->addWidget(m_pLblImage);
        m_pLblImage->setAlignment(Qt::AlignCenter);
        m_pLblImage->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
        
        // slide forward
        QPushButton *pBtnSlideForward = NEW_AS_QT_CHILD( QPushButton,QIcon(":/images/arrow_right.png"), QString(), this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pBtnSlideForward, L"pBtnSlideForward为空", L"GMEP", L"2024-01-30");
        pBtnSlideForward->setObjectName("SlideForward");
        pCentralLayout->addWidget(pBtnSlideForward);
        pBtnSlideForward->setStyleSheet("QPushButton{"
            "background-color:rgba(0,0,0,0);"
            "border:none;"
            "}"
        );
        pBtnSlideForward->setCursor(QCursor(Qt::CursorShape::PointingHandCursor));
        connect(pBtnSlideForward, &QPushButton::clicked, this, &ImageSlider::SlideForward);
                
        // dots layout
        m_pDotsLayout = NEW_AS_QT (QHBoxLayout);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDotsLayout, L"m_pDotsLayout为空", L"GMEP", L"2024-01-30");
        pMainLayout->addLayout(m_pDotsLayout);
        pMainLayout->setAlignment(m_pDotsLayout, Qt::AlignBottom);
        m_pDotsLayout->setContentsMargins(0, 0, 0, 0);
        m_pDotsLayout->setSpacing(5);
        m_pDotsLayout->setAlignment(Qt::AlignHCenter);
        
        // dots signal mapper
        m_pDotsSigalMapper = NEW_AS_QT (QSignalMapper);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDotsSigalMapper, L"m_pDotsSigalMapper为空", L"GMEP", L"2024-01-30");
        connect(m_pDotsSigalMapper, static_cast<void (QSignalMapper:: *)(int)>(&QSignalMapper::mapped), this, &ImageSlider::SlideTo);
        CheckDots();

        // auto play timer
        m_pAutoPlayTimer = NEW_AS_QT(QTimer,this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pAutoPlayTimer, L"m_pAutoPlayTimer为空", L"GMEP", L"2024-01-30");
        m_pAutoPlayTimer->setInterval(3000);
        connect(m_pAutoPlayTimer, &QTimer::timeout, [=]() {
            SlideForward();
        });

        if (m_bAutoPlay)
        {
            m_pAutoPlayTimer->start();
        }
    }

    void ImageSlider::CheckDots()
    {
        int imageKeysCount = (int)m_imageKeys.size();

        // add new
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDotsLayout, L"m_pDotsLayout为空", L"GMEP", L"2024-01-30");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDotsSigalMapper, L"m_pDotsSigalMapper为空", L"GMEP", L"2024-01-30");
        for (int i = (int)m_mpBtnDots.size(); i < imageKeysCount; ++i)
        {
            auto button = std::make_shared<QPushButton>();
            QString dotButtonName = "dotButton" + QString::number(i + 1);
            button->setObjectName(dotButtonName);
            button->setStyleSheet("QPushButton{background:transparent;}");
            button->setIcon(QIcon(QString::fromStdWString(L":/images/circle_#bdc7d5_16x16.png")));
            button->setCursor(Qt::PointingHandCursor);
            button->setFixedSize(8, 8);
            connect(button.get(), &QPushButton::clicked, m_pDotsSigalMapper, static_cast<void (QSignalMapper:: *)()>(&QSignalMapper::map));

            m_mpBtnDots[i] = button;
            m_pDotsLayout->addWidget(button.get());
            m_pDotsSigalMapper->setMapping(button.get(), i);
        }

        // show\hide
        for (int i = 0; i < m_mpBtnDots.size(); ++i)
        {
            if (i < imageKeysCount)
            {
                m_mpBtnDots[i]->setVisible(true);
            }
            else
            {
                m_mpBtnDots[i]->setVisible(false);
            }
        }
    }

    void ImageSlider::UpdateImage(std::wstring imageKey, std::shared_ptr<QImage> spImage)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pImageFrame, L"m_pImageFrame为空", L"GMEP", L"2024-01-30");
        m_pImageFrame->setToolTip(QString());
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblTitle, L"m_pLblTitle为空", L"GMEP", L"2024-01-30");
        m_pLblTitle->clear();
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblImage, L"m_pLblImage为空", L"GMEP", L"2024-01-30");
        m_pLblImage->clear();

        if (m_mpImages.contains(imageKey))
        {
            m_mpImages[imageKey] = spImage;

            auto foundTitleIterator = m_mpImageTitles.find(imageKey);
            if (foundTitleIterator != m_mpImageTitles.end())
            {
                QString title = QString::fromStdWString(foundTitleIterator->second);
                m_pImageFrame->setToolTip(title);

                QString elidedTitle = QFontMetrics(m_pLblTitle->font()).elidedText(title, Qt::TextElideMode::ElideRight, m_pLblTitle->width() - 5 * 2);
                m_pLblTitle->setText(elidedTitle);
            }

            if (spImage)
            {       
                if (m_stretch)
                {
                    QSize availableSize = m_pLblImage->size();
                    m_pLblImage->setPixmap(QPixmap::fromImage(spImage->scaled(availableSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                }
                else
                {
                    m_pLblImage->setPixmap(QPixmap::fromImage(*spImage));
                }     
            }
        }
    }
}
